package com.ruoyi.framework.websocket.WebSocketServer;

import com.ruoyi.framework.websocket.SemaphoreUtils;
import com.ruoyi.framework.websocket.WebSocketUsers;
import jakarta.annotation.PostConstruct;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.*;

/**
 * WebSocket服务：后端模拟设备轨迹（或查询数据库），进行插值并实时推送
 */
@Component
@ServerEndpoint("/websocket/carInfo")
public class CarInfo {

    private static final Logger LOGGER = LoggerFactory.getLogger(CarInfo.class);

    private static final int socketMaxOnlineCount = 100;
    private static final Semaphore socketSemaphore = new Semaphore(socketMaxOnlineCount);
    private static final Set<String> sessionSet = ConcurrentHashMap.newKeySet();

    // 起始点
    private static volatile Point lastPoint = new Point(87.59303, 43.742245);
    private static volatile Point currentPoint = new Point(87.59303, 43.742245);

    // 插值缓存
    private static final Map<String, Queue<Point>> interpolationQueueMap = new ConcurrentHashMap<>();
    private static final int interpolationCount = 5;

    // 任务线程池
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
    private static ScheduledFuture<?> fetchFuture;

    // 控制是否移动
    private static volatile boolean isMoving = true;
    private static volatile int cycleCount = 0;

    @OnOpen
    public void onOpen(Session session) {
        try {
            if (!SemaphoreUtils.tryAcquire(socketSemaphore)) {
                WebSocketUsers.sendMessageToUserByText(session, "连接数已达上限");
                session.close();
                return;
            }

            WebSocketUsers.put(session.getId(), session);
            sessionSet.add(session.getId());
            LOGGER.info("连接建立: {}", session.getId());

            if (fetchFuture == null || fetchFuture.isCancelled()) {
                startSimulateFetchTask();
            }

        } catch (Exception e) {
            LOGGER.error("连接异常", e);
        }
    }

    @OnClose
    public void onClose(Session session) {
        WebSocketUsers.remove(session.getId());
        sessionSet.remove(session.getId());
        SemaphoreUtils.release(socketSemaphore);
        LOGGER.info("连接关闭: {}", session.getId());

        if (sessionSet.isEmpty() && fetchFuture != null) {
            fetchFuture.cancel(false);
            LOGGER.info("无人在线，定时任务已停止");
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        LOGGER.error("连接异常: {}", session.getId(), error);
        try {
            session.close();
        } catch (Exception ignored) {}
        onClose(session);
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        LOGGER.info("收到消息: {} => {}", session.getId(), message);
    }

    @PostConstruct
    public void initPushLoop() {
        scheduler.scheduleAtFixedRate(() -> {
            Queue<Point> queue = interpolationQueueMap.get("GLOBAL");
            if (queue != null && !queue.isEmpty()) {
                Point p = queue.poll();
                String json = String.format("{\"x\": %.6f, \"y\": %.6f}", p.x, p.y);
                WebSocketUsers.sendMessageToAllByText(json);
            }
        }, 0, 1000, TimeUnit.MILLISECONDS);
    }

    private void startSimulateFetchTask() {
        LOGGER.info("启动模拟数据任务");

        fetchFuture = scheduler.scheduleAtFixedRate(() -> {
            // 判断当前状态是否移动
            if (isMoving) {
                lastPoint = currentPoint;
                currentPoint = getNextPoint();
            } else {
                lastPoint = currentPoint; // 静止：不变
            }

            // 生成插值点
            List<Point> interpolated = new ArrayList<>();
            List<Point> temp = generateInterpolatedPoints(lastPoint, currentPoint, interpolationCount);

            // 添加前3个为插值点
            for (int i = 0; i < 3 && i < temp.size(); i++) {
                interpolated.add(temp.get(i));
            }

            // 后2个保持不变（模拟停止）
            Point last = interpolated.get(interpolated.size() - 1);
            while (interpolated.size() < interpolationCount) {
                interpolated.add(new Point(last.x, last.y));
            }

            interpolationQueueMap.put("GLOBAL", new LinkedList<>(interpolated));

            // 控制移动与停止的周期（移动3轮，静止1轮）
            cycleCount++;
            if (cycleCount % 4 == 0) {
                isMoving = false;
                LOGGER.info("模拟状态：车辆停止");
            } else {
                isMoving = true;
                LOGGER.info("模拟状态：车辆移动");
            }

        }, 0, 5000, TimeUnit.MILLISECONDS);
    }

    private Point getNextPoint() {
        return new Point(currentPoint.x + 0.0015, currentPoint.y + 0.0008);
    }

    private List<Point> generateInterpolatedPoints(Point from, Point to, int count) {
        List<Point> result = new ArrayList<>();
        for (int i = 1; i <= count; i++) {
            double t = i / (double) count;
            double progress = easeInOutQuad(t);
            double x = from.x + progress * (to.x - from.x);
            double y = from.y + progress * (to.y - from.y);
            result.add(new Point(x, y));
        }
        return result;
    }

    private double easeInOutQuad(double t) {
        return (t < 0.5) ? (2 * t * t) : (-1 + (4 - 2 * t) * t);
    }

    static class Point {
        double x, y;
        Point(double x, double y) {
            this.x = x;
            this.y = y;
        }
    }
}
